import type {
  ElementIdentifierConfig,
  ElementIdentifierItem,
  ElementIdentifierItemConfig,
  ElementIdentifierResult,
} from './types'
import { logger, loggerDeduplicator } from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'
import { ELEMENT_IDENTIFIER_CONFIG } from './types'

/**
 * 元素标识符 - 负责配置验证、数据管理和查询功能
 */
export class ElementIdentifier {
  private readonly name: string = 'ElementIdentifier'
  static instance: ElementIdentifier | null = null
  private configuration: ElementIdentifierConfig = ELEMENT_IDENTIFIER_CONFIG
  private elementCache: Map<string, ElementIdentifierResult> = new Map()
  private validationErrors: string[] = []
  private categorySet: Set<string> = new Set()
  private subCategorySet: Set<string> = new Set()
  private idSet: Set<string> = new Set()

  /**
   * 获取单例实例
   */
  static getInstance(): ElementIdentifier {
    if (!ElementIdentifier.instance) {
      ElementIdentifier.instance = new ElementIdentifier()
    }
    return ElementIdentifier.instance
  }

  get api() {
    return {
      /**
       * 根据 ID 获取元素配置
       */
      getElement: (id: string): ElementIdentifierResult | undefined => this.getElementById(id),

      /**
       * 根据 ID 获取中文名称
       */
      getName: (id: string): string | undefined => this.getNameById(id),

      /**
       * 根据 ID 获取英文名称
       */
      getEName: (id: string): string | undefined => this.getEnglishNameById(id),

      /**
       * 验证配置
       */
      validate: (): any => this.validateConfiguration(),

      /**
       * 获取统计信息
       */
      getStats: (): any => this.getStatistics(),
    }
  }

  /**
   * 初始化缓存和数据
   * @private
   */
  init(): void {
    this.clearAll()
    this.validateConfiguration()

    // 遍历配置，构建缓存
    Object.entries(this.configuration).forEach(([category, subCategories]) => {
      this.processCategory(category, subCategories)
    })
  }

  /**
   * 处理分类配置
   * @private
   */
  private processCategory(category: string, subCategories: ElementIdentifierItem): void {
    this.categorySet.add(category)

    Object.entries(subCategories).forEach(([subCategory, elementConfig]) => {
      const elementKey = `${category}.${subCategory}`
      this.subCategorySet.add(elementKey)

      if (elementConfig && typeof elementConfig === 'object') {
        this.elementCache.set(elementConfig.id, {
          ...elementConfig,
          category,
          subCategory,
          eName: subCategory, // 英文名取子分类名
        })
        this.idSet.add(elementConfig.id)
      }
    })
  }

  /**
   * 验证配置的完整性和正确性
   */
  private validateConfiguration(): { isValid: boolean, errors: string[], warnings: string[] } {
    this.validationErrors = []
    const warnings: string[] = []

    logger.info(`[${this.name}] ${SYMBOLS.UI.SEARCH} 开始验证元素标识符配置...`)

    // 1. 检查分类不能重复
    this.checkCategoryDuplicates()

    // 2. 检查子分类不能重复
    this.checkSubCategoryDuplicates()

    // 3. 检查ID规则
    this.checkIdRules()

    // 4. 检查名称规则
    this.checkNameRules()

    // 5. 检查数据结构完整性
    this.checkDataStructure()

    const isValid = this.validationErrors.length === 0

    if (isValid) {
      logger.success(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} 元素标识符配置验证通过`)
    }
    else {
      logger.error(`[${this.name}] 元素标识符配置验证失败:`, this.validationErrors)
    }

    return {
      isValid,
      errors: [...this.validationErrors],
      warnings,
    }
  }

  /**
   * 检查分类重复性
   * @private
   */
  private checkCategoryDuplicates(): void {
    const categories = Object.keys(this.configuration)
    const uniqueCategories = new Set(categories)

    if (categories.length !== uniqueCategories.size)
      this.validationErrors.push('存在重复的分类名称')

    logger.info(`[${this.name}] ${SYMBOLS.DOCUMENTS.OPEN_FOLDER} 分类数量: ${categories.length}, 唯一分类: ${uniqueCategories.size}`)
  }

  /**
   * 检查子分类重复性
   */
  private checkSubCategoryDuplicates(): void {
    const allSubCategories: string[] = []

    Object.values(this.configuration).forEach((subCategories: ElementIdentifierItem) => {
      if (subCategories && typeof subCategories === 'object') {
        allSubCategories.push(...Object.keys(subCategories))
      }
    })

    const uniqueSubCategories = new Set(allSubCategories)

    if (allSubCategories.length !== uniqueSubCategories.size)
      this.validationErrors.push('存在重复的子分类名称（跨分类重复）')

    // 检查每个分类内的子分类重复
    Object.entries(this.configuration).forEach(([category, subCategories]) => {
      if (subCategories && typeof subCategories === 'object') {
        const subCategoryKeys = Object.keys(subCategories)
        const uniqueKeys = new Set(subCategoryKeys)

        if (subCategoryKeys.length !== uniqueKeys.size)
          this.validationErrors.push(`分类 '${category}' 内存在重复的子分类名称`)
      }
    })

    logger.info(`[${this.name}] ${SYMBOLS.DOCUMENTS.OPEN_FOLDER} 子分类数量: ${allSubCategories.length}, 唯一子分类: ${uniqueSubCategories.size}`)
  }

  /**
   * 检查 ID 规则
   * @private
   */
  private checkIdRules(): void {
    const seenIds = new Set<string>()

    Object.entries(this.configuration).forEach(([category, subCategories]) => {
      if (subCategories && typeof subCategories === 'object') {
        Object.entries(subCategories).forEach(([subCategory, elementConfig]: [string, ElementIdentifierItemConfig]) => {
          if (!elementConfig || typeof elementConfig !== 'object') {
            this.validationErrors.push(`分类 '${category}.${subCategory}' 配置格式错误`)
            return
          }

          const { id } = elementConfig

          // 检查 ID 是否为空
          if (!id || id.trim() === '') {
            this.validationErrors.push(`分类 '${category}.${subCategory}' 的 ID 不能为空`)
            return
          }

          // 检查 ID 组成部分是否匹配
          if (id !== `${category}.${subCategory}`) {
            this.validationErrors.push(`ID '${id}' 格式不正确，应为 '分类.子分类' 格式`)
            return
          }

          // 检查 ID 重复
          if (seenIds.has(id)) {
            this.validationErrors.push(`ID '${id}' 重复`)
          }
          else {
            seenIds.add(id)
          }
        })
      }
    })

    logger.info(`[${this.name}] ${SYMBOLS.UI.ID} 唯一 ID 数量: ${seenIds.size}`)
  }

  /**
   * 检查名称规则
   */
  private checkNameRules(): void {
    Object.entries(this.configuration).forEach(([_category, subCategories]) => {
      if (subCategories && typeof subCategories === 'object') {
        Object.entries(subCategories).forEach(([_subCategory, elementConfig]: [string, any]) => {
          if (!elementConfig || typeof elementConfig !== 'object')
            return

          const { name, id } = elementConfig

          // 检查名称是否为空
          if (!name || name.trim() === '') {
            this.validationErrors.push(`元素 '${id}' 的名称不能为空`)
          }

          // 检查名称长度
          if (name && name.length > 50) {
            this.validationErrors.push(`元素 '${id}' 的名称过长（最大50字符）`)
          }
        })
      }
    })
  }

  /**
   * 检查数据结构完整性
   */
  private checkDataStructure(): void {
    if (!this.configuration || typeof this.configuration !== 'object') {
      this.validationErrors.push('配置必须是一个对象')
      return
    }

    if (Object.keys(this.configuration).length === 0) {
      this.validationErrors.push('配置不能为空')
      return
    }

    // 检查每个分类的结构
    Object.entries(this.configuration).forEach(([category, subCategories]) => {
      if (!subCategories || typeof subCategories !== 'object') {
        this.validationErrors.push(`分类 '${category}' 必须是一个对象`)
      }
      else if (Object.keys(subCategories).length === 0) {
        this.validationErrors.push(`分类 '${category}' 不能为空`)
      }
    })
  }

  /**
   * 根据 ID 获取中文名称
   */
  private getNameById(id: string): string | undefined {
    const element = this.getElementById(id)
    return element?.name
  }

  /**
   * 根据 ID 获取英文名称（取 ID 点后面的部分）
   */
  private getEnglishNameById(id: string): string | undefined {
    const element = this.getElementById(id)
    return element?.eName
  }

  /**
   * 根据 ID 获取完整的元素信息
   */
  private getElementById(id: string): ElementIdentifierResult | undefined {
    if (!id) {
      logger.warn(`[${this.name}] 获取元素信息时 ID 不能为空`)
      return undefined
    }

    const element = this.elementCache.get(id)

    if (!element && id.includes('.'))
      loggerDeduplicator.warn(`[${this.name}] 未找到 ID 为 '${id}' 的元素`)

    return element
  }

  /**
   * 获取所有分类列表
   */
  getAllCategories(): string[] {
    return Array.from(this.categorySet)
  }

  /**
   * 获取所有元素 ID 列表
   */
  getAllElementIds(): string[] {
    return Array.from(this.idSet)
  }

  /**
   * 根据分类获取该分类下的所有元素
   */
  getElementsByCategory(category: string): any[] {
    const categoryConfig = this.configuration[category]
    if (!categoryConfig) {
      logger.warn(`[${this.name}] 分类 '${category}' 不存在`)
      return []
    }

    return Object.values(categoryConfig).filter(Boolean)
  }

  /**
   * 搜索元素（根据名称或 ID 模糊搜索）
   */
  searchElements(keyword: string): any[] {
    if (!keyword || keyword.trim() === '') {
      return []
    }

    const results: any[] = []
    const lowerKeyword = keyword.toLowerCase()

    this.elementCache.forEach((element, id) => {
      if (id.toLowerCase().includes(lowerKeyword)
        || element.name.toLowerCase().includes(lowerKeyword)) {
        results.push(element)
      }
    })

    return results
  }

  /**
   * 获取配置统计信息
   */
  private getStatistics(): {
    totalCategories: number
    totalElements: number
    categories: Record<string, number>
  } {
    const categories: Record<string, number> = {}

    Object.entries(this.configuration).forEach(([category, subCategories]) => {
      if (subCategories && typeof subCategories === 'object') {
        categories[category] = Object.keys(subCategories).length
      }
    })

    return {
      totalCategories: Object.keys(categories).length,
      totalElements: this.elementCache.size,
      categories,
    }
  }

  /**
   * 导出当前配置（深拷贝）
   */
  exportConfiguration(): any {
    return JSON.parse(JSON.stringify(this.configuration))
  }

  /**
   * 重新加载配置
   */
  reloadConfiguration(newConfig: any): void {
    this.configuration = newConfig
    this.init()
    logger.info(`[${this.name}] ${SYMBOLS.STATUS.REFRESH} 配置已重新加载`)
  }

  /**
   * 清空所有缓存数据
   */
  clearAll(): void {
    this.categorySet.clear()
    this.subCategorySet.clear()
    this.idSet.clear()
    this.elementCache.clear()
  }
}
